package mqtt

import (
	"sync"

	openapi "github.com/alibabacloud-go/darabonba-openapi/client"
	mqtt "github.com/alibabacloud-go/onsmqtt-20200420/client"
	"testkjcld.bhecard.com/gitlab/kit/esim/config"
	"testkjcld.bhecard.com/gitlab/kit/esim/log"
)

var (
	poolOnce   sync.Once
	onceClient *MQTTClient
)

type MQTTClient struct {
	mqttClient *mqtt.Client

	accessKey string // AccessKey 阿里云身份验证，在阿里云服务器管理控制台创建

	secretKey string // SecretKey

	endpoint string // 设置HTTP接入域名

	instanceId string // 实例id

	logger log.Logger

	conf config.Config
}

func newMQTTClient(options ...Option) *MQTTClient {
	poolOnce.Do(func() {
		var err error
		onceClient = &MQTTClient{}
		for _, option := range options {
			option(onceClient)
		}

		if onceClient.conf == nil {
			onceClient.conf = config.NewNullConfig()
		}

		if onceClient.logger == nil {
			onceClient.logger = log.NewLogger()
		}

		onceClient.endpoint = onceClient.conf.GetString("aliyun_mqtt_endpoint")
		if onceClient.endpoint == "" {
			onceClient.logger.Panicf("aliyun_mqtt_endpoint is null! please confirm")
		}

		onceClient.accessKey = onceClient.conf.GetString("aliyun_mqtt_access_key")
		if onceClient.accessKey == "" {
			onceClient.logger.Panicf("aliyun_mqtt_access_key is null! please confirm")
		}

		onceClient.secretKey = onceClient.conf.GetString("aliyun_mqtt_secrect_key")
		if onceClient.secretKey == "" {
			onceClient.logger.Panicf("aliyun_secrect_key is null! please confirm")
		}

		onceClient.instanceId = onceClient.conf.GetString("aliyun_mqtt_instance_id")
		if onceClient.instanceId == "" {
			onceClient.logger.Panicf("aliyun_mqtt_instance_id is null! please confirm")
		}

		if onceClient.mqttClient, err = mqtt.NewClient(&openapi.Config{
			AccessKeyId:     &onceClient.accessKey,
			AccessKeySecret: &onceClient.secretKey,
			Endpoint:        &onceClient.endpoint,
		}); err != nil {
			onceClient.logger.Panicf("aliyun mqtt init client err[%v]! please confirm", err)
		}

		onceClient.logger.Infof("[mqtt] init success %s",
			onceClient.endpoint)
	})

	return onceClient
}

type MQTTClientOptions struct{}

type Option func(*MQTTClient)

func (MQTTClientOptions) WithConf(conf config.Config) Option {
	return func(mq *MQTTClient) {
		mq.conf = conf
	}
}

func (MQTTClientOptions) WithLogger(logger log.Logger) Option {
	return func(mq *MQTTClient) {
		mq.logger = logger
	}
}
